home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / stdwin / Ports / mac / draw.c < prev    next >
Text File  |  1995-12-21  |  14KB  |  850 lines

  1. /* MAC STDWIN -- DOCUMENT DRAWING. */
  2.  
  3. /* Contents of this file:
  4.    
  5.    wchange, wscroll;
  6.    wbegindrawing, wenddrawing, _wupdate, wupdate;
  7.    text attribute manipulation (internal and external);
  8.    text measuring;
  9.    text drawing;
  10.    coordinate conversion tools;
  11.    ordinary drawing;
  12.    color stuff.
  13.    
  14.    XXX Should be split, only things used between w{begin,end}drawing
  15.    belong here.
  16.  
  17.    BEWARE OF COORDINATE SYSTEMS!
  18.    
  19.    The window's origin is not always the same.
  20.    When the aplication isn't drawing (i.e., outside w{begin,end}drawing),
  21.    the origin is (0, 0); this is necessary because the control mgr
  22.    doesn't like it otherwise.
  23.    When the application is drawing, the origin is set to win->(orgh, orgv)
  24.    so the drawing primitives don't need to do their own coordinate
  25.    transformation.
  26.    Routines called while not drawing must do their own transformations.
  27.    
  28.    XXX Routines that may be called any time are in trouble!
  29.    (There shouldn't be any.)
  30. */
  31.  
  32. #include "macwin.h"
  33. #include <Fonts.h>
  34. #include <Memory.h>
  35.  
  36. #ifdef __MWERKS__
  37. #define CONSTPATCAST (ConstPatternParam) &
  38. #else
  39. #define CONSTPATCAST /*nothing*/
  40. #endif
  41.  
  42.  
  43. COLOR _w_fgcolor = blackColor;
  44. COLOR _w_bgcolor = whiteColor;
  45. static COLOR save_fgcolor, save_bgcolor;
  46.  
  47. static WINDOW *drawing;
  48. static TEXTATTR drawsaveattr;
  49. static int baseline;
  50. static int lineheight;
  51.  
  52. /* Avoid name conflicts: */
  53.  
  54. #define getfinfo getfinfo_
  55. #define wsetstyle wsetstyle_
  56.  
  57. /* Function prototypes */
  58.  
  59. STATIC void getwattr _ARGS((GrafPtr port, TEXTATTR *attr));
  60. STATIC void setwattr _ARGS((TEXTATTR *attr));
  61. STATIC void getfinfo _ARGS((void));
  62.  
  63. /* Patterns -- can't use the QuickDraw globals (sigh) */
  64.  
  65. static Pattern pat0   = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  66. static Pattern pat25  = {0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44};
  67. static Pattern pat50  = {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
  68. static Pattern pat75  = {0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd};
  69. static Pattern pat100 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  70.  
  71. void
  72. wchange(win, left, top, right, bottom)
  73.     WINDOW *win;
  74.     int left, top, right, bottom;
  75. {
  76.     Rect r;
  77.     
  78.     SetPort(win->w);
  79.     
  80.     if (drawing) dprintf("warning: wchange called while drawing");
  81.     makerect(win, &r, left, top, right, bottom);
  82.     InvalRect(&r);
  83. }
  84.  
  85. void
  86. wscroll(win, left, top, right, bottom, dh, dv)
  87.     WINDOW *win;
  88.     int left, top, right, bottom;
  89.     int dh, dv;
  90. {
  91.     Rect r;
  92.     
  93.     if (drawing) dprintf("warning: wchange called while drawing");
  94.     makerect(win, &r, left, top, right, bottom);
  95.     scrollby(win, &r, dh, dv);
  96. }
  97.  
  98. /* Scroll a rectangle (given in window coordinates) by dh, dv.
  99.    Also used from scroll.c. */
  100. /* XXX need less visible name */
  101.  
  102. void
  103. scrollby(win, pr, dh, dv)
  104.     WINDOW *win;
  105.     Rect *pr;
  106.     int dh, dv;
  107. {
  108.     RgnHandle rgn= NewRgn();
  109.     
  110.     SetPort(win->w);
  111.     
  112.     rmcaret(win);
  113.     
  114.     if (!EmptyRgn(( (WindowPeek)win->w )->updateRgn)) {
  115.         RgnHandle ur= NewRgn();
  116.         int left, top;
  117.         Rect r;
  118.         
  119.         /* Scroll the part of the update region that intersects
  120.            the scrolling area. */
  121.         CopyRgn(( (WindowPeek)win->w )->updateRgn, ur);
  122.         /* portBits.bounds is the screen in local coordinates! */
  123.         left= win->w->portBits.bounds.left;
  124.         top= win->w->portBits.bounds.top;
  125.         OffsetRgn(ur, left, top); /* Global to Local */
  126.         RectRgn(rgn, pr);
  127.         SectRgn(rgn, ur, ur);
  128.         if (!EmptyRgn(ur)) {
  129.             ValidRgn(ur);
  130.             OffsetRgn(ur, dh, dv);
  131.             SectRgn(rgn, ur, ur);
  132.             InvalRgn(ur);
  133.         }
  134.         DisposeRgn(ur);
  135.     }
  136.     
  137.     /* ScrollRect seems to work only in normal mode */
  138.     ForeColor(blackColor);
  139.     BackColor(whiteColor);
  140.     ScrollRect(pr, dh, dv, rgn);
  141.     ForeColor((short)win->fgcolor);
  142.     BackColor((short)win->bgcolor);
  143.     
  144.     InvalRgn(rgn);
  145.     
  146.     DisposeRgn(rgn);
  147. }
  148.  
  149.  
  150. /* Internal version of wupdate -- also used from event.c */
  151.  
  152. void
  153. _wupdate(win, pr)
  154.     WINDOW *win;
  155.     Rect *pr;
  156. {
  157.     RgnHandle rgn= NewRgn();
  158.     
  159.     SetPort(win->w);
  160.     
  161.     rmcaret(win);
  162.     BeginUpdate(win->w);
  163.     EraseRect(&win->w->portRect);
  164.     _wgrowicon(win);
  165.     DrawControls(win->w);
  166.     getwinrect(win, pr);
  167.     RectRgn(rgn, pr);
  168.     SectRgn(rgn, win->w->visRgn, rgn);
  169.     *pr= (*rgn)->rgnBBox;
  170.     OffsetRect(pr, win->orgh, win->orgv);
  171.     if (win->drawproc != NULL && !EmptyRect(pr)) {
  172.         wbegindrawing(win);
  173.         (*win->drawproc)(win, pr->left, pr->top, pr->right, pr->bottom);
  174.         wenddrawing(win);
  175.     }
  176.     EndUpdate(win->w);
  177.     DisposeRgn(rgn);
  178. }
  179.  
  180. /* Process an update event -- call the window's draw procedure. */
  181. /* XXX This function shouldn't be in the stdwin spec (why was it ever?) */
  182.  
  183. void
  184. wupdate(win)
  185.     WINDOW *win;
  186. {
  187.     if (win->drawproc != NULL) {
  188.         Rect r;
  189.         _wupdate(win, &r);
  190.     }
  191. }
  192.  
  193. void
  194. wbegindrawing(win)
  195.     WINDOW *win;
  196. {
  197.     Rect r;
  198.     
  199.     if (drawing != NULL) {
  200.         dprintf("warning: recursive call to wbegindrawing");
  201.         /* Fix it */
  202.         wenddrawing(drawing);
  203.     }
  204.     if (win == NULL) {
  205.         dprintf("warning: wbegindrawing(NULL) ignored");
  206.         return;
  207.     }
  208.     drawing= win;
  209.     SetPort(win->w);
  210.     SetOrigin(win->orgh, win->orgv);
  211.     rmcaret(win);
  212.     getwinrect(win, &r);
  213.     ClipRect(&r);
  214.     PenNormal();
  215.     wgettextattr(&drawsaveattr);
  216.     wsettextattr(&win->attr);
  217.     
  218.     save_fgcolor = _w_fgcolor;
  219.     save_bgcolor = _w_bgcolor;
  220.     _w_fgcolor = win->fgcolor;
  221.     _w_bgcolor = win->bgcolor;
  222.     _w_usefgcolor(_w_fgcolor);
  223.     _w_usebgcolor(_w_bgcolor);
  224. }
  225.  
  226. void
  227. wenddrawing(win)
  228.     WINDOW *win;
  229. {
  230.     Rect r;
  231.     
  232.     if (drawing == NULL) {
  233.         dprintf("warning: wenddrawing ignored while not drawing");
  234.         return;
  235.     }
  236.     if (drawing != win) {
  237.         dprintf("warning: wenddrawing ignored for wrong window");
  238.         return;
  239.     }
  240.     
  241.     _w_fgcolor = save_fgcolor;
  242.     _w_bgcolor = save_bgcolor;
  243.     _w_usefgcolor(win->fgcolor);
  244.     _w_usebgcolor(win->bgcolor);
  245.     
  246.     SetOrigin(0, 0);
  247.     SetRect(&r, -32000, -32000, 32000, 32000);
  248.     ClipRect(&r);
  249.     wsettextattr(&drawsaveattr);
  250.     drawing= NULL;
  251. }
  252.  
  253. /* Get the current text attributes of a GrafPort. */
  254.  
  255. static void
  256. getwattr(port, attr)
  257.     GrafPtr port;
  258.     TEXTATTR *attr;
  259. {
  260.     SetPort(port); /* XXX Is this necessary to validate txFont etc.? */
  261.     
  262.     attr->font= port->txFont;
  263.     attr->style= port->txFace;
  264.     attr->size= port->txSize;
  265. }
  266.  
  267. /* Start using the given text attributes in the current grafport. */
  268.  
  269. static void
  270. setwattr(attr)
  271.     TEXTATTR *attr;
  272. {
  273.     TextFont(attr->font);
  274.     TextFace(attr->style & ~TX_INVERSE);
  275.     TextSize(attr->size);
  276. }
  277.  
  278. /* Get font info and baseline from current GrafPort */
  279.  
  280. static void
  281. getfinfo()
  282. {
  283.     FontInfo finfo;
  284.     GetFontInfo(&finfo);
  285.     baseline= finfo.ascent + finfo.leading;
  286.     lineheight= baseline + finfo.descent;
  287. }
  288.  
  289. /* Initialize 'wattr'.  Uses the screen's grafport. */
  290.  
  291. int _w_font= applFont;
  292. int _w_size= 9;
  293.  
  294. void
  295. initwattr()
  296. {
  297.     TEXTATTR saveattr;
  298.     
  299.     SetPort(screen);
  300.     
  301.     getwattr(screen, &saveattr);
  302.     TextFont(_w_font);
  303.     TextSize(_w_size);
  304.     getwattr(screen, &wattr);
  305.     getfinfo();
  306.     setwattr(&saveattr);
  307. }
  308.  
  309. /* TEXT ATTRIBUTES. */
  310.  
  311. void
  312. wgettextattr(attr)
  313.     TEXTATTR *attr;
  314. {
  315.     *attr= wattr;
  316. }
  317.  
  318. void
  319. wsettextattr(attr)
  320.     TEXTATTR *attr;
  321. {
  322.     wattr= *attr;
  323.     if (drawing != NULL) {
  324.         setwattr(attr);
  325.         getfinfo();
  326.     }
  327. }
  328.  
  329. void
  330. wgetwintextattr(win, attr)
  331.     WINDOW *win;
  332.     TEXTATTR *attr;
  333. {
  334.     *attr= win->attr;
  335. }
  336.  
  337. void
  338. wsetwintextattr(win, attr)
  339.     WINDOW *win;
  340.     TEXTATTR *attr;
  341. {
  342.     win->attr= *attr;
  343.     if (drawing != NULL)
  344.         dprintf("warning: wsetwintextattr called while drawing");
  345. }
  346.  
  347. char **
  348. wlistfontnames(pat, plen)
  349.     char *pat;
  350.     int *plen;
  351. {
  352.     /* XXX not yet implemented */
  353.     *plen = 0;
  354.     return NULL;
  355. }
  356.  
  357. int
  358. wsetfont(fontname)
  359.     char *fontname;
  360. {
  361.     int ret = 1;
  362.     if (fontname == NULL || *fontname == EOS)
  363.         wattr.font= _w_font;
  364.     else {
  365.         short fnum= 0;
  366.         GetFNum(PSTRING(fontname), &fnum);
  367.         if (fnum == 0) {
  368.             dprintf("can't find font %s", fontname);
  369.             ret = 0;
  370.         }
  371.         wattr.font= fnum;
  372.     }
  373.     if (drawing != NULL) {
  374.         TextFont(wattr.font);
  375.         getfinfo();
  376.     }
  377.     return ret;
  378. }
  379.  
  380. void
  381. wsetsize(size)
  382.     int size;
  383. {
  384.     wattr.size= size;
  385.     if (drawing != NULL) {
  386.         TextSize(size);
  387.         getfinfo();
  388.     }
  389. }
  390.  
  391. void
  392. wsetstyle(face)
  393.     Style face;
  394. {
  395.     wattr.style= face;
  396.     if (drawing != NULL) {
  397.         TextFace(face & ~TX_INVERSE);
  398.         getfinfo();
  399.     }
  400. }
  401.  
  402. void
  403. wsetplain()
  404. {
  405.     wsetstyle(0);
  406. }
  407.  
  408. void
  409. wsetinverse()
  410. {
  411.     wattr.style |= TX_INVERSE;
  412. }
  413.  
  414. void
  415. wsetbold()
  416. {
  417.     wsetstyle(bold);
  418. }
  419.  
  420. void
  421. wsetitalic()
  422. {
  423.     wsetstyle(italic);
  424. }
  425.  
  426. void
  427. wsetbolditalic()
  428. {
  429.     wsetstyle(bold|italic);
  430. }
  431.  
  432. void
  433. wsetunderline()
  434. {
  435.     wsetstyle(underline);
  436. }
  437.  
  438. void
  439. wsethilite()
  440. {
  441.     wsetstyle(TX_INVERSE);
  442. }
  443.  
  444. /* TEXT MEASURING. */
  445.  
  446. int
  447. wlineheight()
  448. {
  449.     if (drawing == NULL) {
  450.         TEXTATTR saveattr;
  451.         getwattr(screen, &saveattr);
  452.         setwattr(&wattr);
  453.         getfinfo();
  454.         setwattr(&saveattr);
  455.     }
  456.     return lineheight;
  457. }
  458.  
  459. int
  460. wbaseline()
  461. {
  462.     if (drawing == NULL)
  463.         (void) wlineheight();
  464.     return baseline;
  465. }
  466.  
  467. int
  468. wtextwidth(str, len)
  469.     char *str;
  470.     int len;
  471. {
  472.     TEXTATTR saveattr;
  473.     int width;
  474.     
  475.     if (drawing == NULL) {
  476.         getwattr(screen, &saveattr);
  477.         setwattr(&wattr);
  478.     }
  479.     if (len < 0)
  480.         len= strlen(str);
  481.     width= TextWidth(str, 0, len);
  482.     if (drawing == NULL)
  483.         setwattr(&saveattr);
  484.     return width;
  485. }
  486.  
  487. int
  488. wcharwidth(c)
  489.     int c;
  490. {
  491.     char cbuf[1];
  492.     cbuf[0]= c;
  493.     return wtextwidth(cbuf, 1);
  494. }
  495.  
  496. /* TEXT DRAWING. */
  497.  
  498. void
  499. wdrawtext(h, v, str, len)
  500.     int h, v;
  501.     char *str;
  502.     int len;
  503. {
  504.     Point pen;
  505.     
  506.     if (len < 0)
  507.         len= strlen(str);
  508.     MoveTo(h, v + baseline);
  509.     DrawText(str, 0, len);
  510.     GetPen(&pen);
  511.     if (wattr.style & TX_INVERSE) {
  512.         Rect r;
  513.         SetRect(&r, h, v, pen.h, v + lineheight);
  514.         InvertRect(&r);
  515.     }
  516. }
  517.  
  518. void
  519. wdrawchar(h, v, c)
  520.     int h, v;
  521.     int c;
  522. {
  523.     if ((wattr.style & TX_INVERSE) == 0) {
  524.         /* Attempt to optimize for appls. like dpv */
  525.         MoveTo(h, v + baseline);
  526.         DrawChar(c);
  527.     }
  528.     else {
  529.         char cbuf[1];
  530.         cbuf[0]= c;
  531.         wdrawtext(h, v, cbuf, 1);
  532.     }
  533. }
  534.  
  535. /* COORDINATE CONVERSIONS ETC. */
  536.  
  537. /* Create a rect in current window coordinates (as for getwinrect)
  538.    from a rectangle given in document coordinates.
  539.    This works both while drawing and while not drawing.
  540.    The resulting rectangle is clipped to the winrect. */
  541.  
  542. void
  543. makerect(win, pr, left, top, right, bottom)
  544.     WINDOW *win;
  545.     Rect *pr;
  546.     int left, top, right, bottom;
  547. {
  548.     Rect r;
  549.     SetRect(pr, left, top, right, bottom);
  550.     if (!drawing)
  551.         OffsetRect(pr, - win->orgh, - win->orgv);
  552.     getwinrect(win, &r);
  553.     (void) SectRect(&r, pr, pr);
  554. }
  555.  
  556. /* Retrieve the 'winrect', i.e., the contents area exclusive
  557.    of the scroll bars and grow icon.
  558.    Coordinates are in window coordinates, i.e.,
  559.    the origin is (0, 0) outside w{begin,end}drawing,
  560.    but (win->orgh, win->orgv) between calls to these routines. */
  561.  
  562. void
  563. getwinrect(win, pr)
  564.     WINDOW *win;
  565.     Rect *pr;
  566. {
  567.     *pr= win->w->portRect;
  568.     if (win->vbar != NULL)
  569.         pr->right -= BAR;
  570.     if (win->hbar != NULL)
  571.         pr->bottom -= BAR;
  572. }
  573.  
  574. /* ACTUAL DRAW ROUTINES. */
  575.  
  576. void
  577. wdrawline(h1, v1, h2, v2)
  578. {
  579.     MoveTo(h1, v1);
  580.     Line(h2-h1, v2-v1);
  581. }
  582.  
  583. void
  584. wxorline(h1, v1, h2, v2)
  585. {
  586.     MoveTo(h1, v1);
  587.     PenMode(patXor);
  588.     Line(h2-h1, v2-v1);
  589.     PenNormal();
  590. }
  591.  
  592. void
  593. wdrawbox(left, top, right, bottom)
  594.     int left, top, right, bottom;
  595. {
  596.     Rect r;
  597.     
  598.     SetRect(&r, left, top, right, bottom);
  599.     FrameRect(&r);
  600. }
  601.  
  602. void
  603. werase(left, top, right, bottom)
  604.     int left, top, right, bottom;
  605. {
  606.     Rect r;
  607.     
  608.     SetRect(&r, left, top, right, bottom);
  609.     EraseRect(&r);
  610. }
  611.  
  612. void
  613. winvert(left, top, right, bottom)
  614.     int left, top, right, bottom;
  615. {
  616.     Rect r;
  617.     
  618.     SetRect(&r, left, top, right, bottom);
  619.     InvertRect(&r);
  620. }
  621.  
  622. void
  623. wpaint(left, top, right, bottom)
  624.     int left, top, right, bottom;
  625. {
  626.     Rect r;
  627.     
  628.     SetRect(&r, left, top, right, bottom);
  629.     FillRect(&r, CONSTPATCAST drawing->w->pnPat);
  630. }
  631.  
  632. void
  633. wshade(left, top, right, bottom, perc)
  634.     int left, top, right, bottom;
  635.     int perc;
  636. {
  637.     Rect r;
  638.     PatPtr p;
  639.     
  640.     perc= (perc + 12)/25;
  641.     CLIPMIN(perc, 0);
  642.     
  643.     switch (perc) {
  644.     case 0:    p = &pat0;    break;
  645.     case 1: p = &pat25;    break;
  646.     case 2: p = &pat50;     break;
  647.     case 3: p = &pat75;    break;
  648.     default: p = &pat100;    break;
  649.     }
  650.     
  651.     SetRect(&r, left, top, right, bottom);
  652.  
  653.     FillRect(&r, (ConstPatternParam)p);
  654. }
  655.  
  656. void
  657. wdrawcircle(h, v, radius)
  658.     int h, v;
  659.     int radius;
  660. {
  661.     Rect r;
  662.     
  663.     SetRect(&r, h-radius, v-radius, h+radius, v+radius);
  664.     FrameOval(&r);
  665. }
  666.  
  667. void
  668. wfillcircle(h, v, radius)
  669.     int h, v;
  670.     int radius;
  671. {
  672.     Rect r;
  673.     
  674.     SetRect(&r, h-radius, v-radius, h+radius, v+radius);
  675.     FillOval(&r, CONSTPATCAST drawing->w->pnPat);
  676. }
  677.  
  678. void
  679. wxorcircle(h, v, radius)
  680.     int h, v;
  681.     int radius;
  682. {
  683.     Rect r;
  684.     
  685.     SetRect(&r, h-radius, v-radius, h+radius, v+radius);
  686.     InvertOval(&r);
  687. }
  688.  
  689. /* Draw counterclockwise elliptical arc.
  690.    h, v are center; hrad, vrad are half axes; ang1 and ang2 are start
  691.    and stop angles in degrees, with respect to 3 o'clock. */
  692.  
  693. void
  694. wdrawelarc(h, v, hrad, vrad, ang1, ang2)
  695. {
  696.     Rect r;
  697.     SetRect(&r, h-hrad, v-vrad, h+hrad, v+vrad);
  698.     FrameArc(&r, 90-ang1, ang1-ang2);
  699. }
  700.  
  701. /* Fill an elliptical arc */
  702.  
  703. void
  704. wfillelarc(h, v, hrad, vrad, ang1, ang2)
  705. {
  706.     Rect r;
  707.     SetRect(&r, h-hrad, v-vrad, h+hrad, v+vrad);
  708.     FillArc(&r, 90-ang1, ang1-ang2, CONSTPATCAST drawing->w->pnPat);
  709. }
  710.  
  711. /* Invert an elliptical arc */
  712.  
  713. void
  714. wxorelarc(h, v, hrad, vrad, ang1, ang2)
  715. {
  716.     Rect r;
  717.     SetRect(&r, h-hrad, v-vrad, h+hrad, v+vrad);
  718.     InvertArc(&r, 90-ang1, ang1-ang2);
  719. }
  720.  
  721. /* Draw a polyline of n-1 connected segments (not necessarily closed).
  722.    This means n points.  Points are given as an array of POINTs. */
  723.  
  724. void
  725. wdrawpoly(n, points)
  726.     int n;
  727.     POINT *points;
  728. {
  729.     if (--n > 0) {
  730.         MoveTo(points[0].h, points[0].v);
  731.         do {
  732.             points++;
  733.             LineTo(points[0].h, points[0].v);
  734.         } while (--n > 0);
  735.     }
  736. }
  737.  
  738. /* Fill a polygon of n points */
  739.  
  740. void
  741. wfillpoly(n, points)
  742.     int n;
  743.     POINT *points;
  744. {
  745.     PolyHandle ph = OpenPoly();
  746.     wdrawpoly(n, points);
  747.     ClosePoly();
  748.     FillPoly(ph, CONSTPATCAST drawing->w->pnPat);
  749.     DisposHandle((Handle)ph);
  750. }
  751.  
  752. /* Invert a polygon of n points */
  753.  
  754. void
  755. wxorpoly(n, points)
  756.     int n;
  757.     POINT *points;
  758. {
  759.     PolyHandle ph = OpenPoly();
  760.     wdrawpoly(n, points);
  761.     ClosePoly();
  762.     InvertPoly(ph);
  763.     DisposHandle((Handle)ph);
  764. }
  765.  
  766. /* CLIPPING */
  767.  
  768. void
  769. wcliprect(left, top, right, bottom)
  770.     int left, top, right, bottom;
  771. {
  772.     Rect r1, r2;
  773.     SetRect(&r1, left, top, right, bottom);
  774.     getwinrect(drawing, &r2);
  775.     SectRect(&r1, &r2, /*dst:*/ &r2);
  776.     ClipRect(&r2);
  777.  
  778. }
  779.  
  780. void
  781. wnoclip()
  782. {
  783.     Rect r;
  784.     getwinrect(drawing, &r);
  785.     ClipRect(&r);
  786. }
  787.  
  788. /* COLOR */
  789.  
  790. COLOR
  791. wgetfgcolor()
  792. {
  793.     return _w_fgcolor;
  794. }
  795.  
  796. COLOR
  797. wgetbgcolor()
  798. {
  799.     return _w_bgcolor;
  800. }
  801.  
  802. void
  803. wsetfgcolor(color)
  804.     COLOR color;
  805. {
  806.     _w_fgcolor = color;
  807.     if (drawing)
  808.         _w_usefgcolor(color);
  809. }
  810.  
  811. void
  812. wsetbgcolor(color)
  813.     COLOR color;
  814. {
  815.     _w_bgcolor = color;
  816.     if (drawing)
  817.         _w_usebgcolor(color);
  818. }
  819.  
  820. void
  821. _w_usefgcolor(color)
  822.     COLOR color;
  823. {
  824.     ForeColor((short)color);
  825.     switch (((color >> 16) + 32) / 64) {
  826.     case 0:
  827.         PenPat(CONSTPATCAST pat100);
  828.         break;
  829.     case 1:
  830.         PenPat(CONSTPATCAST pat75);
  831.         break;
  832.     case 2:
  833.         PenPat(CONSTPATCAST pat50);
  834.         break;
  835.     case 3:
  836.         PenPat(CONSTPATCAST pat25);
  837.         break;
  838.     case 4:
  839.         PenPat(CONSTPATCAST pat0);
  840.         break;
  841.     }
  842. }
  843.  
  844. void
  845. _w_usebgcolor(color)
  846.     COLOR color;
  847. {
  848.     BackColor((short)color);
  849. }
  850.